#pragma once
#include "Sem.hpp"
#include "Mutex.hpp"
#include <unistd.h>
#include <pthread.h>
#include <vector>
#include <semaphore.h>
#include <iostream>

using namespace MutexModule;

namespace RingBufferModule
{
    template<typename T>
    class RingBuffer
    {
    public:
        RingBuffer(int cap):_cap(cap),_ring(cap),_p_step(0),_c_step(0),
        _datasem(0),_spacesem(cap)
        {
        }
        //为什么在代码中没有做判断？---本身就是表示资源数目的，只要成功，就一定有，不需要判断
        void Equeue(const T& in)
        {
            //生产者做的,先p操作
            _spacesem.p();
            LockGuard Lock(_p_lock);
            _ring[_p_step++] = in;//生产数据
            //因为数据多了一份就需要v操作
            _p_step %= _cap; //维持环形特性
            _datasem.v();
        }
        void Pop(T* out)
        {
            //消费者在消费----V()操作
            _datasem.p();    //预定一个数据
            LockGuard Lock(_c_lock);
            *out = _ring[_c_step++];
            _c_step %= _cap;    //维持环形特性
            _spacesem.v();
        }
        ~RingBuffer(){
        }
    private:
        std::vector<T> _ring;          // 环
        int _cap;                      // 环的固定容量
        int _p_step;                   // 生产者位置
        int _c_step;                   // 消费者位置
        SemMoule::Sem _datasem;        // 数据信号量
        SemMoule::Sem _spacesem;       // 空间信号量

        Mutex _p_lock;       //生产者的锁   
        Mutex _c_lock;       //消费者的锁
    };
}